function gewThirdPersonCamera(avatarNode) {
  gewCamera.call(this);  
  // Camera properties
  this.m_fov = 60.0;
  this.m_aspect = 1.0;
  this.m_near = 1.0;
  this.m_far = 1000.0;  
  this.m_desired_fov = this.m_fov;
  this.m_desired_pos = new gewVec3(0.0, 0.0, 1.0);
  this.m_up = new gewVec3(0.0, 1.0, 0.0);
  this.m_look_at_position = new gewVec3(0.0, 0.0, 0.0);
  // ThirdPerson Camera properties
  this.avatarNode = avatarNode;
  this.avatarPositionOffset = new gewVec3(0,1.5,0);
  this.thirdPersonDirection = new gewVec3(0,1,1);
  this.thirdPersonDirection.normalize();
  this.thirdPersonDistance = 5;
  this.thirdPersonMinDistance = 1.5;
  this.thirdPersonMaxDistance = 35;
  this.thirdPersonMinAngle = 10; // min angle between thirdPersonDirection and 0y (0,1,0)
  this.thirdPersonMaxAngle = 130;// max angle between thirdPersonDirection and 0y (0,1,0)
  
  this.thirdPersonZoomSensitive = 240;
  this.thirdPersonRotateSensitive = 60; 
  // PRIVATE:
  this.currentAvatarPosition = new gewVec3(0,0,0);
  this.thirdPersonReference = new gewVec3(0,0,0);
  this.thirdPersonDirection.mulScalar(this.thirdPersonDistance,this.thirdPersonReference);
}
extend2(gewThirdPersonCamera, gewCamera);

gewThirdPersonCamera.prototype.setDistance = function( dis){
  this.thirdPersonDistance = dis;
  this.thirdPersonDirection.mulScalar(this.thirdPersonDistance,this.thirdPersonReference);
  this.setCameraFlag(CAMERA_UPDATE_VIEW_MATRIX, true);
}
gewThirdPersonCamera.prototype.setDirection = function(dir){
  this.thirdPersonDirection.set(dir.x,dir.y,dir.z);
  this.thirdPersonDirection.mulScalar(this.thirdPersonDistance,this.thirdPersonReference);
  this.setCameraFlag(CAMERA_UPDATE_VIEW_MATRIX, true);
}
gewThirdPersonCamera.prototype.prepareRender = function(){
  var avatarPos = this.avatarNode.position;
  var currentAvatarPos = this.currentAvatarPosition;
  if( !avatarPos.isEqual(currentAvatarPos) || this.getCameraFlag(CAMERA_UPDATE_VIEW_MATRIX) )
  {
    currentAvatarPos.set(avatarPos.x,avatarPos.y,avatarPos.z);
    var new_desired_pos = currentAvatarPos.add(this.avatarPositionOffset).add(this.thirdPersonReference);
    this.setDesiredPos(new_desired_pos);
    this.setLookAt(currentAvatarPos.add(this.avatarPositionOffset));
    this.setUp(new gewVec3(0,1,0));
  }
  gewCamera.prototype.prepareRender.call(this);
};
gewThirdPersonCamera.prototype.onMouseUp = function(e) 
{
  this.mousekey = -1;
}

gewThirdPersonCamera.prototype.onMouseDown = function(e)
{
  this.mousekey = e.button;
  this.start_point = new gewVec2(e.canvasX, e.canvasY);
}
gewThirdPersonCamera.prototype.onMouseMove = function(e)
{ 
  var cur_point = new gewVec2(e.canvasX, e.canvasY); 
  if (this.mousekey == GEW_MOUSE_LEFT && e.altKey == true) {
    var old_angle = this.thirdPersonDirection.angleFrom( new gewVec3(0,1,0))* GEW_MATH_RADIAN_TO_DEGREE;
    var delta_x = -(cur_point.x - this.start_point.x)/this.thirdPersonRotateSensitive;
    var delta_y = (cur_point.y - this.start_point.y)/this.thirdPersonRotateSensitive;
    var offset_vec_right = this.m_right.mulScalar(delta_x);
    var offset_vec_up = this.m_up.mulScalar(delta_y);
    var new_dir = this.thirdPersonDirection.add(offset_vec_right).add(offset_vec_up);
    new_dir.normalize();
    var angle = new_dir.angleFrom( new gewVec3(0,1,0))* GEW_MATH_RADIAN_TO_DEGREE;
    if (angle > this.thirdPersonMinAngle&&
        angle < this.thirdPersonMaxAngle) {
      this.setDirection(new_dir);
      if(angle>=70)
      {
        if (angle <= 90) {
          var delta = (angle - old_angle) / (90 - 70) * (this.previousDistance - this.thirdPersonMinDistance);
          var new_dis = this.thirdPersonDistance - delta;
          if (new_dis > this.thirdPersonMinDistance &&
          new_dis < this.thirdPersonMaxDistance) {
            this.setDistance(new_dis);
          }
        }
      }
      else
      {
        this.previousDistance = this.thirdPersonDistance;
      }
    }
  }
  this.start_point = cur_point;
}
gewThirdPersonCamera.prototype.onMouseWheel = function(e){
  var delta = 0;
  if (e.wheelDelta) {
    delta = event.wheelDelta / this.thirdPersonZoomSensitive; 
    if (window.opera) delta = -delta;
  } else if (event.detail) {
    delta = -event.detail / this.thirdPersonZoomSensitive;
  }  
  var new_dis = this.thirdPersonDistance - (delta* this.thirdPersonDistance/3) ;
  if( new_dis > this.thirdPersonMinDistance &&
      new_dis < this.thirdPersonMaxDistance)
  {
    this.setDistance(new_dis);  
  }
}
